package com.junpuxin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.junpuxin.dto.*;
import com.junpuxin.entity.EmpRole;
import com.junpuxin.entity.Role;
import com.junpuxin.excel.RoleExcel;
import com.junpuxin.exception.IllegalParamException;
import com.junpuxin.exception.ServerErrorException;
import com.junpuxin.exception.VersionException;
import com.junpuxin.mapper.RoleMapper;
import com.junpuxin.service.RoleService;
import com.junpuxin.vo.RoleVO;
import jakarta.annotation.Resource;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author junpuxin
 */
@Service
@CacheConfig(cacheNames = "role")
public class RoleServiceImpl implements RoleService {

    @Resource
    private RoleMapper roleMapper;

    @CacheEvict(allEntries = true)
    @Override
    public int insert(RoleInsertDTO dto) {
        Role role = BeanUtil.copyProperties(dto, Role.class);
        // 设置默认值
        if(StrUtil.isBlank(dto.getInfo())) {
            role.setInfo("暂无描述");
        }
        role.setVersion(0L);
        role.setDeleted(0);
        role.setCreated(LocalDateTime.now());
        role.setUpdated(LocalDateTime.now());
        // DB添加
        int result = roleMapper.insert(role);
        if (result < 0) {
            throw new ServerErrorException("DB添加失败");
        }
        return result;
    }

    @Cacheable(key = "#p0", condition = "#p0 != null", unless = "#result == null")
    @Override
    public Role select(Long id) {
        // DB查询
        Role result = roleMapper.select(id);
        if(ObjectUtil.isNull(result)) {
            throw new ServerErrorException("ID不存在");
        }
        return result;
    }

    @Cacheable(key = "#root.methodName", unless = "#result == null")
    @Override
    public List<RoleVO> list() {
        return roleMapper.list(new RolePageDTO())
                .stream()
                .map(role -> BeanUtil.copyProperties(role, RoleVO.class))
                .collect(Collectors.toList());
    }

    @Cacheable(key = "#root.methodName + ':' + #p0.toString()",
                condition = "#p0 != null",
                unless = "#result == null")
    @Override
    public PageInfo<Role> page(RolePageDTO dto) {
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        return new PageInfo<>(roleMapper.list(dto));
    }

    @CacheEvict(allEntries = true)
    @Transactional
    @Retryable(retryFor = VersionException.class)
    @Override
    public int update(RoleUpdateDTO dto) {
        Long id = dto.getId();
        if(ObjectUtil.isNull(id)) {
            throw new IllegalParamException("ID为空");
        }
        Role role = roleMapper.select(id);
        if(ObjectUtil.isNull(role)) {
            throw new ServerErrorException("记录不存在");
        }
        BeanUtil.copyProperties(dto, role);
        // 设置默认值
        role.setUpdated(LocalDateTime.now());
        // DB修改
        int result = roleMapper.update(role);
        if (result <= 0) {
            throw new VersionException("DB修改失败");
        }
        return result;
    }

    @CacheEvict(allEntries = true)
    @Override
    public int delete(Long id) {
        int result = roleMapper.delete(id);
        if (result <= 0) {
            throw new ServerErrorException("DB删除失败");
        }
        return result;
    }

    @CacheEvict(allEntries = true)
    @Override
    public int deleteBatch(List<Long> ids) {
        int result = roleMapper.deleteBatch(ids);
        if (result <= 0) {
            throw new ServerErrorException("DB批量删除失败");
        }
        return result;
    }

    @Override
    public List<RoleExcel> getExcelData() {
        return roleMapper.list(new RolePageDTO())
                .stream()
                .map(role -> BeanUtil.copyProperties(role, RoleExcel.class))
                .collect(Collectors.toList());
    }

    @Cacheable(key = "#p0", condition = "#p0 != null", unless = "#result == null")
    @Override
    public List<Role> listByEmpId(Long empId) {
        List<Role> roles = roleMapper.listByEmpId(empId);
        if (ObjectUtil.isNull(roles)) {
            throw new ServerErrorException("记录不存在");
        }
        return roles;
    }

    @CacheEvict(allEntries = true)
    @Transactional
    @Retryable(retryFor = VersionException.class)
    @Override
    public int updateByEmpId(Long empId, List<Long> roleIds) {
        // 删除该员工的全部中间表记录
        int deleteResult = roleMapper.deleteEmpRoleByEmpId(empId);
        // 创建该员工的新角色列表
        List<EmpRole> empRoles = new ArrayList<>();
        for (Long roleId : roleIds) {
            EmpRole empRole = new EmpRole();
            empRole.setFkRoleId(roleId);
            empRole.setFkEmpId(empId);
            empRole.setVersion(0L);
            empRole.setDeleted(0);
            empRole.setCreated(LocalDateTime.now());
            empRole.setUpdated(LocalDateTime.now());
            empRoles.add(empRole);
        }
        // 批量添加该员工的角色记录(中间表记录)
        int insertResult = roleMapper.insertEmpRoleBatch(empRoles);
        return deleteResult + insertResult;
    }
}
